﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using IniParser;
using IniParser.Model;
using MolyMart.WithOPC;

namespace MolyMart
{
    public class Controller
    {
        private readonly string _iniFilePath = @"MolyMart.ini";
        private readonly BlockingCollection<ServerValuesItem> _valuesQueue = new BlockingCollection<ServerValuesItem>(new ConcurrentQueue<ServerValuesItem>(),short.MaxValue);
        private Initializer _initializer;
        private BlockingCollection<MessageItem> _messageQueue = new BlockingCollection<MessageItem>(new ConcurrentQueue<MessageItem>(),short.MaxValue);
        private Collector _collector;

        public void Start()
        {
            StartCollector();
            RunWithOpc();
        }
        private List<OpcServerDefinition> ReadConfigForOpcServers( )
        {
            var opcServerDefinitions = new List<OpcServerDefinition>();
            var parser = new FileIniDataParser();
            var configData = parser.ReadFile(_iniFilePath);
            var totalServers = configData["OPCServers"].Count;
            for (var x = 0; x < totalServers; x++)
            {
                var serverStrings = configData["OPCServers"][$"Server{x}"].Split('|');
                if (serverStrings.Length != 5)
                {
                    throw new Exception("Corrupted INI File!");
                }
                if (!bool.Parse(serverStrings[4].Trim()))
                {
                    continue;
                }
                var opcServerDefinition = new OpcServerDefinition
                {
                    HostName = serverStrings[0].Trim(),
                    ServerName = serverStrings[1].Trim(),
                    Id = serverStrings[2].Trim(),
                    Case = serverStrings[3].Trim(),
                    ValuesNameDictionary = new Dictionary<string, string>(),
                    Items = new List<OpcItemDefinition>()
                };
                var totalItems = configData[serverStrings[3]].Count;
                for (var y = 0; y < totalItems; y++)
                {
                    var itemStrings = configData[serverStrings[3]][$"S{y}"].Split('|');
                    if (itemStrings.Length != 3)
                    {
                        throw new Exception("Corrupted INI File");
                    }
                    var opcItemDefinition = new OpcItemDefinition
                    {
                        Item = itemStrings[0].Trim(),
                        Name = itemStrings[1].Trim(),
                        Type = itemStrings[2].Trim()
                    };
                    opcServerDefinition.ValuesNameDictionary[opcItemDefinition.Item] = opcItemDefinition.Name;
                    opcServerDefinition.Items.Add(opcItemDefinition);
                }
                opcServerDefinitions.Add(opcServerDefinition);
            }
            return opcServerDefinitions;
        }

        private void RunWithOpc()
        {
            _initializer = new Initializer(ReadConfigForOpcServers(),_valuesQueue,_messageQueue);
            _initializer.Start();
        }

        private void StartCollector(int collectorThreads = 1)
        {
            bool[] threads = new bool[collectorThreads];
            foreach (var b in threads)
            {
                var collectorThread = new Thread(() =>
                {
                    _collector = new Collector(_valuesQueue);
                    _collector.Start();
                }) {IsBackground = true};
                collectorThread.Start();
            } 
        }
    }
}
